在上個禮拜裡,我們介紹了一些很常見的 feature,我們接下來看看如何在 OpenType 裡實現他們。
用來標記 feature 的「語言」其實並沒有統一的規定,如 Adobe 開發的 AFKDO(Adobe Font Development Kit for OpenType)、Microsoft 的 VOLT (Visual OpenType Layout Tool) 等等。
在這裡,我們會介紹最通用的 AFKDO 語言。
額外注意的是,AFKDO 僅僅是一種標記用的語言,跟 HTML 類似,他本身僅僅用來描述,並沒有辦法進行複雜的邏輯判斷。
A 到 Z、數字、英文句點(.)、以及底線(_)命名。uniXXXX 開頭,而輔助平面上的(五位數的 Unicode)則為 uXXXXX。$ 可以是 uni0024,也可以是 dollar;Ω可以是 uni03A9,也可以是 Omega;あ 可以是 uni3042,也可以是 a-hira。
<parent>.<child> 來表示同字母的父子關係,例如 A.sc 就是和 A 有關。<alphabet>-<script> 則用來表示同一種文字系統,例如「ㄅ(b-bopomofo)、ㄆ(p-bopomofo)」;「あ(a-hira)、さ(sa-hira)」;「Д(De-cy)、Ж(Zhe-cy)」,看得出來是同一家人。.notdef 字符之外,字元名稱不能以 , 和 - 開頭。
a、Kappa、space、dollar、uni60C5、twodots、j.full、m_hungarumlautcomb 都是可用的字符名稱2dots、.uni597D、._.A 則無法使用[ ... ] 的方式將數個字符名稱包在其中,用空格分開,使其視為同一類別
space [endash emdash figuredash] space
space endash space 且 space emdash space 且 space figuredash space
- 字符取得一定的範圍
[<firstGlyph> - <lastGlyph>]
[A.swash - Z.swash] 或 [a - z] 或 [0 - 9]
@<name> = [ ... ]
@dash = [endash emdash figuredash]; 進行 assignspace @dash space
@Vowels.lc = [a e i o u];
@Vowels.uc = [A E I O U];
@Vowels = [@Vowels.lc @Vowels.uc];
# 等價於
@Vowels = [a e i o u A E I O U];
feature <name> [useExtension] {
# rules...
} <name>;
其中,<name> 為 feature 的名字。長度恆為四個字母,必須要和 OpenType 規格的定義相同,否則無法被軟體正確的讀取與啟用。當該區塊的規則超過 64 KB 時,可以透過 [useExtension] 語法拓展要寫入的規則。每行最後應該使用分號 ; 表示結尾。
例如以下是一個把 ff 處理成 f_f 連字的特性規則:
feature liga {
sub f f by f_f;
} liga;
feature <name> {
…
} <name>;
等價於
feature <name> {
lookup <label> {
…
} <label>;
} <name>;
這樣的好處,在於可以透過 label 更清楚標示我們要替換的規則,例如下方的 pnum 特性包裝了用於拉丁字母的 pnum_latin 跟阿拉伯字母的 pnum_arab:
feature pnum {
lookup pnum_latin {
sub zero by zero.prop;
sub one by one.prop;
sub two by two.prop;
...
} pnum_latin;
lookup pnum_arab {
sub uni0660 by uni0660.prop;
sub uni0661 by uni0661.prop;
sub uni0662 by uni0662.prop;
...
} pnum_arab;
} sups;
甚至可以在不同的 feature 中引用同一組 lookup 規則,讓版面更好閱讀
lookup myAlternates {
sub A by A.001; # Alternate form
...
} myAlternates;
feature salt { lookup myAlternates; } salt;
feature ss01 { lookup myAlternates; } ss01;
從前面介紹的連字、上下文替代、文體集與字符組成等等,不難發現他們背後的邏輯都是「替換」(lookup)。在 OpenType 裡總共定義了八種替換方式,如下表所示:
| Value | Type | 替換規則 |
|---|---|---|
| 1 | Single | 將一個字符換成另一個字符 |
| 2 | Multiple | 將一個字符換成多個字符 |
| 3 | Alternate | 將一個字符換成多個可能字符之一 |
| 4 | Ligature | 將多個字符換成另一個字符 |
| 5 | Context | 根據前後文替換多個字符 |
| 6 | Chaining Context | 根據串接的前後文替換多個字符 |
| 7 | Extension Substitution | 用於擴充 |
| 8 | Reverse chaining context single | 根據連續前後文反方向替換多個字符(通常用於阿拉伯文) |
對應前幾天我們所介紹的 feature 們:
| feature | 中文 | Lookup | 預設 |
|---|---|---|---|
| liga | 標準連字 | 4 | 預設開啟,但可關閉的連字 |
| dlig | 可擇連字 | 4 | 預設不開啟 |
| hlig | 歷史連字 | 4 | 預設不開啟 |
| smcp | 小寫轉小型大寫字母 | 1 | 預設不開啟 |
| c2sc | 大寫轉小型大寫字母 | 1 | 預設不開啟 |
| swsh | 花飾字 | 1 | 預設不開啟 |
| salt | 預設文體替代字 | 1 | 預設不開啟,通常建議等於ss01 |
| ss01-ss20 | 文體集 | 1 | 預設不開啟 |
| calt | 上下文替代字 | 6 | 預設開啟 |
| vert | 竪排 | 1 | 預設開啟 |
| vrt2 | 竪排・改 | 1 | 預設開啟 |
| ccmp | 字符分解與組合 | 4, 2 | 強制套用 |
學習完基本語法後,我們會在明天繼續介紹如何編寫